﻿using Report_IDal.Basic;
using Report_Model.Db;
using Report_Unity.Basic;
using Report_Unity.Log;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Report_Dal.Basic
{
    public class BaseDal<T> : IBaseDal<T> where T : class, new()
    {
        private LogHelper logHelper = new LogHelper(typeof(BaseDal<T>));

        /// <summary>
        /// 注入DbContext
        /// </summary>
        public DbContext DbContext { get; set; }

        public BaseDal(string conn)
        {
            if(conn == ConfigSource.tab_tj)
            {
                DbContext = new Medical_SXEYEntities();
            }
            else
            {
                DbContext = new GroupReportEntities();
            }
        }
     

        public bool Add(T t)
        {
            DbContext.Set<T>().Add(t);
            return SaveChanges();
        }

        public bool AddList(List<T> list)
        {
            list.ForEach(a =>
            {
                DbContext.Set<T>().Add(a);
            });
            return SaveChanges();
        }

        public bool Up(T t)
        {
            DbContext.Entry<T>(t).State = EntityState.Modified;
            return SaveChanges();
        }

        public bool UpList(List<T> list)
        {
            list.ForEach(a =>
            {
                DbContext.Entry<T>(a).State = EntityState.Modified;
            });
            return SaveChanges();
        }

        public bool UpArray(params T[] ts)
        {
            ts.ToList().ForEach(a =>
            {
                if (a != null)
                {
                    DbContext.Entry<T>(a).State = EntityState.Modified;
                }

            });
            return SaveChanges();
        }

        public bool Del(T t)
        {
            DbContext.Entry(t).State = EntityState.Deleted;
            return SaveChanges();
        }

        public bool DelList(List<T> list)
        {
            list.ForEach(a =>
            {
                DbContext.Entry(a).State = EntityState.Deleted;
            });


            return SaveChanges();
        }

        public IQueryable<T> Get(Expression<Func<T, bool>> whereLambda)
        {
            return DbContext.Set<T>().Where<T>(whereLambda);
        }

        public IQueryable<T> GetAsNoTracking(Expression<Func<T, bool>> whereLambda)
        {
            return DbContext.Set<T>().AsNoTracking().Where(whereLambda);
        }

        public IQueryable<T> GetPage<s>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, s>> orderLambda, bool flag = true)
        {
            var temp = DbContext.Set<T>().AsNoTracking().Where<T>(whereLambda);
            totalCount = temp.Count<T>(); // 返回总记录数

            if (flag)
            {
                temp = temp.OrderBy<T, s>(orderLambda).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
            }
            else
            {
                temp = temp.OrderByDescending<T, s>(orderLambda).Skip<T>((pageIndex - 1) * pageSize).Take<T>(pageSize);
            }

            return temp;
        }

        public List<T> GetSelectIn(Expression<Func<T, string>> keyField, List<string> list)
        {
            string databaseName = typeof(T).Name;
            string field = keyField.GetPropertyName();

            string listStr = list.HandleListStr();
            //  string listStr = string.Format("'{0}'", string.Join(",", list).Replace(",", "','"));
            string sql = $"SELECT * FROM {databaseName} WHERE {field} IN({listStr})";
            return DbContext.Database.SqlQuery<T>(sql).ToList();
        }

        public bool SaveChanges()
        {
            bool flag = false;
            try
            {
                if (DbContext.SaveChanges() > 0)
                    flag = !flag;
            }
            catch (Exception e)
            {
                logHelper.Error(e.ToString());
                Console.WriteLine(e);
            };

            return flag;
        }

        public int GetNextSort(Expression<Func<T, bool>> whereLambda, Expression<Func<T, int>> selector)
        {
            List<int> listSort = GetAsNoTracking(whereLambda).Select(selector).ToList();
            int maxSort = 0;

            if (listSort != null && listSort.Count > 0)
                maxSort = listSort.Max();

            return maxSort + 1;
        }

        public ResultInfo MoveObj(Expression<Func<T, bool>> whereLambda, Func<T, bool> whereid, Expression<Func<T, int>> keySelector, string dirc)
        {
            // 按照这个排序
            List<T> list = Get(whereLambda).OrderBy(keySelector).ToList();
            if (list == null || list.Count == 0)
                return CodeStatus.error_202.GetStatus();

            // 获取当前的默认
            T t = list.Where(whereid).FirstOrDefault();

            string sortFeild = keySelector.GetPropertyName();
            return HandleMove(list, dirc, t, sortFeild);
        }

        private ResultInfo HandleMove(List<T> list, string dirc, T t, string sortFeild)
        {
            int maxIndex = list.Count - 1;
            //  t = list.Where(a => a.ID == id).FirstOrDefault();
            // 获取当前问题的索引
            int currIndex = list.IndexOf(t);
            if (currIndex == -1) return CodeStatus.error_214.GetStatus();

            if (ConfigSource.up == dirc)
            {
                // 如果sort==1不能再上移动
                if (currIndex == 0) return CodeStatus.error_212.GetStatus();
                int prevIndex = currIndex - 1;

                return Move(list, prevIndex, t, sortFeild);

            }
            else if (ConfigSource.down == dirc)
            {
                if (currIndex == maxIndex) return CodeStatus.error_212.GetStatus();
                int nextIndex = currIndex + 1;

                return Move(list, nextIndex, t, sortFeild);
            }
            else
            {
                return CodeStatus.error_201.GetStatus("dirc只能是up或者down");
            }
        }

        private ResultInfo Move(List<T> list, int index, T currT, string sortFeild)
        {
            T t = list[index];
            if (t == null) return CodeStatus.error_213.GetStatus();
            PropertyInfo tp = t.GetType().GetProperty(sortFeild); ;
            // 当前的排序号
            PropertyInfo currP = currT.GetType().GetProperty(sortFeild);

            int tempSort = int.Parse(currP.GetValue(currT).ToString());
            // 另外的Sort
            currP.SetValue(currT, int.Parse(tp.GetValue(t).ToString()));
            // 待修改的
            tp.SetValue(t, tempSort);

            if (!UpArray(t, currT))
                return CodeStatus.error_301.GetStatus("移动失败");

            return CodeStatus.success.GetStatus();
        }

        public string GetNextId(Expression<Func<T, string>> fnnc, bool year = false, bool month = false, bool day = false, int num = 7)
        {
            string id = DbContext.Set<T>().Max(fnnc);
            if (string.IsNullOrEmpty(id))
            {
                StringBuilder sb = new StringBuilder();
                if (year)
                    sb.Append(DateTime.Now.Year.ToString());

                if (month)
                    sb.Append(DateTime.Now.Month < 10 ? "0" + DateTime.Now.Month.ToString() : DateTime.Now.Month.ToString());

                if (day)
                    sb.Append(DateTime.Now.Day < 10 ? "0" + DateTime.Now.Day.ToString() : DateTime.Now.Day.ToString());
                //maxIdStr += DateTime.Now.Day < 10 ? "0" + DateTime.Now.Day.ToString() : DateTime.Now.Day.ToString();

                id = "1";
                id = id.PadLeft(num, '0');
                sb.Append(id);
                return sb.ToString();
            }

            long maxid = long.Parse(id) + 1;
            string maxIdStr = maxid.ToString();
            if (maxIdStr.Length <= num)
                maxIdStr = maxIdStr.PadLeft(num, '0');

            return maxIdStr;
        }

        public long GetNextId(Expression<Func<T, long>> fnnc)
        {
            long id = DbContext.Set<T>().Max(fnnc);
            id += 1;
            return id;
        }

        public int GetNextId(Expression<Func<T, int>> fnnc)
        {
            int id = DbContext.Set<T>().Max(fnnc);
            id += 1;
            return id;
        }
    }
}
